package util

import (
	"path/filepath"

	"github.com/glennliao/apijson-go/consts"
	"github.com/glennliao/apijson-go/model"
)

// 是否首字母大写 检查字符串首字母是否大写
func S是否首字母大写(字符串 string) bool {
	if len(字符串) == 0 {
		return false
	}
	首字母 := 字符串[0]
	return 首字母 >= 'A' && 首字母 <= 'Z'
}

// 存在首字母大写的键 用于判断是否存在查询节点
func C存在首字母大写的键(映射 model.Map) bool {
	for 键 := range 映射 {
		if S是否首字母大写(键) {
			return true
		}
	}
	return false
}

// 移除后缀 移除字符串后缀
func Y移除后缀(键 string, 后缀 string) string {
	return 键[0 : len(键)-len(后缀)]
}

// 解析引用列 解析引用字段
// 将 "id@":"[]/User/userId"  解析出引用信息
func X解析引用列(引用字符串 string) (引用路径 string, 引用列 string) {
	引用列 = filepath.Base(引用字符串) // userId
	if 引用列 == 引用字符串 {
		return 引用字符串, ""
	}
	引用路径 = 引用字符串[0 : len(引用字符串)-len(引用列)-1] // []/User
	return 引用路径, 引用列
}

// 分析顺序 使用拓扑排序分析节点获取优先级
func F分析顺序(依赖关系 [][]string) ([]string, error) {
	节点映射 := make(map[string]bool)
	for _, 依赖项 := range 依赖关系 {
		节点映射[依赖项[0]] = true
		节点映射[依赖项[1]] = true
	}

	节点数量 := len(节点映射)
	边映射 := make(map[string][]string)
	入度 := make(map[string]int)
	结果 := []string{}

	for _, 依赖项 := range 依赖关系 {
		边映射[依赖项[1]] = append(边映射[依赖项[1]], 依赖项[0])
		入度[依赖项[0]]++
	}

	队列 := []string{}

	for 节点 := range 节点映射 {
		if 入度[节点] == 0 {
			队列 = append(队列, 节点)
		}
	}

	for len(队列) > 0 {
		var 首个节点 string
		首个节点, 队列 = 队列[0], 队列[1:]
		结果 = append(结果, 首个节点)
		for _, 节点 := range 边映射[首个节点] {
			入度[节点]--
			if 入度[节点] == 0 {
				队列 = append(队列, 节点)
			}
		}
	}

	if len(结果) != 节点数量 {
		return nil, consts.X新建请求验证错误("节点循环依赖")
	}

	return 结果, nil
}
